#ifndef ZSC_H_INCLUDED
#define ZSC_H_INCLUDED
#include <vector>
#include <string>
#include <iostream>
#include <fstream>
#include <algorithm>



class Player {
public:
    class Spell
    {
    private:
        std::string name;
        int dmg;
        bool available;
    public:
        Spell();
        Spell(std::string sname, int sdmg, bool av);// : name(sname), dmg(sdmg), available(av) {}
        int getDmg();

        bool getAvailable();
        void setAvailable(bool b);
        std::string getName();
    };

    Player();
    Player(std::string sname);
    int getSpellNum();
    void addSp(int i);
    int getAtk();
    int getDef();
    Spell getSpecAbility(int which);
    std::vector<Spell> getAllSpell();
    virtual void lvlUp() =0;
    virtual std::string getClass() = 0;

    int getXp();
    int getLvl();
    int getBoredom();
    void changeBoredom(int bor);
    void addXP(int sxp);
    void Set(int satk,int sdef);
    void makeTheMatching(int abnum,std::vector<std::string> ab);
    void addLvl();
    void setLvl(int slvl);
    std::string getName();

    void addAbility(Spell s);
    virtual ~Player() {}
private:
    int atk;
    int def;
    std::vector<Spell> ability;
    int xp;
    int lvl;
    int boredom;
    int spellnum;
    std::string name;
};

class Rogue : public Player
{
public:


    void lvlUp()
    {

        int atk=getAtk();
        int def =getDef();
        Set(atk+3,def+1);
        addLvl();
        addXP(-1*getXp());
        if (getLvl()%3==0)
        {
            int i = rand() % getAllSpell().size() + getSpellNum();
            addSp(i);
        }

    }

    std::string getClass() { return "Rogue"; }

    ~Rogue() { }
    Rogue(std::string name) : Player(name)
    {
        Set(3,5);
        std::ifstream f;
        f.open("rspells.txt");
        std::string sname;
        int sdmg;
        bool sav;
        for(int i=0;i<5;++i)
        {
            f >> sname;
            f >> sdmg;
            f >> sav;
            Spell s(sname,sdmg,sav);
            addAbility(s);
        }
        f.close();
    }
//    ~Rogue() {}
};

class Warrior : public Player
{
public:
    void lvlUp()
    {
        int atk=getAtk();
        int def =getDef();
        Set(atk+2,def+2);
        addLvl();
        addXP(-1*getXp());
        if (getLvl()%4==0)
        {
            int i = rand() % getAllSpell().size() + getSpellNum();
            addSp(i);
        }

    }

    std::string getClass() { return "Warrior"; }

    Warrior() { }
    Warrior(std::string name) : Player(name)
    {
        Set(2,5);
        std::ifstream f;
        f.open("wspells.txt");
        std::string sname;
        int sdmg;
        bool sav;
        for(int i=0;i<5;++i)
        {
            f >> sname;
            f >> sdmg;
            f >> sav;
            Spell s(sname,sdmg,sav);
            addAbility(s);
        }
        f.close();
    }
    ~Warrior() {}
};

class Mage : public Player
{
public:
    void lvlUp()
    {
        int atk=getAtk();
        int def =getDef();
        Set(atk+1,def+1);
        addLvl();
        addXP(-1*getXp());
        if (getLvl()%2==0)
        {
            int i = rand() % getAllSpell().size() + getSpellNum();
            addSp(i);
        }

    }

    std::string getClass() { return "Mage"; }

    Mage() {}
    Mage(std::string name) : Player(name)
    {
        Set(1,5);
        std::ifstream f;
        f.open("mspells.txt");
        std::string sname;
        int sdmg;
        bool sav;
        for(int i=0;i<5;++i)
        {
            f >> sname;
            f >> sdmg;
            f >> sav;
            Spell s(sname,sdmg,sav);
            addAbility(s);
        }
        f.close();
    }
    ~Mage() {}
};

#endif // ZSC_H_INCLUDED
